package com.iteaj.iot.test.serial;

import com.fazecast.jSerialComm.SerialPort;
import com.iteaj.iot.FrameworkManager;
import com.iteaj.iot.IotThreadManager;
import com.iteaj.iot.modbus.Payload;
import com.iteaj.iot.modbus.client.rtu.ModbusRtuClientMessage;
import com.iteaj.iot.serial.SerialClient;
import com.iteaj.iot.serial.SerialConnectProperties;
import com.iteaj.iot.serial.SerialPortCreator;
import com.iteaj.iot.test.IotTestHandle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.iteaj.iot.test.TestConst.LOGGER_SERIAL_DESC;

@Component
@ConditionalOnExpression("${iot.test.serial-start:false}")
public class SerialTestHandle implements IotTestHandle {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void start() throws Exception {
        System.out.println("------------------------------------------------------ 开始串口测试 ---------------------------------------------");
        List<SerialPort> available = SerialPortCreator.available();
        String serialPort1 = "com3", serialPort2 = "com4";
        if(available.size() >= 2) {
            serialPort1 = available.get(0).getSystemPortName();
            serialPort2 = available.get(1).getSystemPortName();
        }
        SerialConnectProperties connectProperties = new SerialConnectProperties(serialPort1);
        connectProperties.setReaderIdleTime(5); // 设置读阻塞5秒
        SerialClient com1 = SerialPortCreator.open(connectProperties);// 打开串口1
        SerialClient com2 = SerialPortCreator.openByAsync(new SerialConnectProperties(serialPort2), 5, (receivedData, protocol) -> {
            String value = new String(receivedData);
            if(value.equals("54321")) {
                logger.info(LOGGER_SERIAL_DESC, "异步读(固定长度)", "通过");
            } else {
                logger.error(LOGGER_SERIAL_DESC, "异步读(固定长度)", "失败");
            }
        });// 打开串口2

        long delay = connectProperties.getReaderIdleTime() - 1;
        IotThreadManager.instance().getExecutorService().schedule(() -> {
            com2.write("54321".getBytes()); // 读超时测试
        }, delay, TimeUnit.SECONDS);

        byte[] bytes = new byte[5];
        long timeMillis = System.currentTimeMillis();
        com1.read(bytes);
        long l = System.currentTimeMillis() - timeMillis;
        String value = new String(bytes);
        com1.write(bytes); // 写到com2做异步测试
        if(l >= delay * 1000 && value.equals("54321")) {
            logger.info(LOGGER_SERIAL_DESC, "阻塞读", "通过");
        } else {
            logger.error(LOGGER_SERIAL_DESC, "阻塞读", "失败");
        }

        IotThreadManager.instance().getExecutorService().schedule(() -> {
            com2.write("12".getBytes());
        }, 1, TimeUnit.SECONDS);
        IotThreadManager.instance().getExecutorService().schedule(() -> {
            com2.write("34".getBytes());
        }, 2, TimeUnit.SECONDS);
        bytes = new byte[5];
        long timeMillis1 = System.currentTimeMillis();
        int readNum = com1.read(bytes);
        long l1 = System.currentTimeMillis() - timeMillis1;
        if((l1 >= (connectProperties.getReaderIdleTime() * 1000)) && readNum == 4) {
            logger.info(LOGGER_SERIAL_DESC, "阻塞读(长度不满足)", "通过");
        } else  {
            logger.error(LOGGER_SERIAL_DESC, "阻塞读(长度不满足)", "失败");
        }

        com2.disconnect();
        SerialPortCreator.openByAsync(new SerialConnectProperties(serialPort2), "\r".getBytes(), ((receivedData, protocol) -> {
            String value1 = new String(receivedData);
            if(value1.equals("54321\r")) {
                logger.info(LOGGER_SERIAL_DESC, "异步读(分隔符)", "通过");
            } else {
                logger.error(LOGGER_SERIAL_DESC, "异步读(分隔符)", "失败");
            }
        }));

        com1.write("54321\r".getBytes(StandardCharsets.UTF_8));

        TimeUnit.SECONDS.sleep(2);
        com1.close(); com2.close();
    }

    @Override
    public int getOrder() {
        return 5500;
    }
}
